package com.woniuxy.service.impl;

import cn.hutool.crypto.SecureUtil;
import com.github.pagehelper.PageInfo;
import com.woniuxy.entity.dto.DictionaryDTO;
import com.woniuxy.entity.dto.operations.*;
import com.woniuxy.entity.po.dic.Dictionary;
import com.woniuxy.entity.po.operations.Card;
import com.woniuxy.entity.po.operations.Client;
import com.woniuxy.entity.po.operations.Vehicle;
import com.woniuxy.entity.po.operations.VehicleImg;
import com.woniuxy.mapper.CardMapper;
import com.woniuxy.mapper.ClientMapper;
import com.woniuxy.mapper.VehicleMapper;
import com.woniuxy.service.ClientService;
import com.woniuxy.util.*;
import lombok.AllArgsConstructor;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @BelongsProject: charging-management-platform
 * @BelongsPackage: com.woniuxy.service
 * @Author: Quan
 * @Date: 2025/3/30 14:55
 */
@Service
@AllArgsConstructor
@Transactional
public class ClientServiceImpl implements ClientService {
	private ClientMapper clientMapper;
	private PageHelperUtil pageHelperUtil;
	private RedisTemplate<String, Object> redisTemplate;
	//	private RedisAboutDicUtils redisAboutDicUtils;
	private MinioUtils minioUtils;
	private VehicleMapper vehicleMapper;
	private CardMapper cardMapper;
	private static final String REDIS_KEY_CONST_CLIENTTYPE = RedisKeyConst.DICTIONARY_KEY + "CLIENTTYPE";
	private static final String REDIS_KEY_CONST_ACCOUNTTYPE = RedisKeyConst.DICTIONARY_KEY + "ACCOUNTTYPE";

	/**
	 * @Description: 展示全部用户用于点卡中的选择客户
	 * @Param: [pageParam]
	 * @return: com.woniuxy.util.ResponseData<?>
	 * @Author: Quan
	 * @Date: 2025/3/30
	 */
	@Override
	public ResponseData<?> queryAllClientToSelect(PageParam<ClientForCardSelectDisplayDTO> pageParam) {

		return ResponseData.ok(pageHelperUtil.getPageInfo(pageParam, clientMapper::queryAllClientToSelect, ClientForCardSelectDisplayDTO::new));
	}

	/**
	 * @Description: 查询全部用户用于展示
	 * @Param: [pageParam]
	 * @return: com.woniuxy.util.ResponseData<?>
	 * @Author: Quan
	 * @Date: 2025/3/31
	 */
	@Override
	public ResponseData<?> queryAll(PageParam<ClientDisplayDTO> pageParam) {
		return ResponseData.ok(pageHelperUtil.getPageInfo(pageParam, clientMapper::queryAll, ClientDisplayDTO::new));
	}

	@Override
	public ResponseData<?> forbiddenById(Long id) {
		clientMapper.forbiddenById(id);
		return ResponseData.ok();
	}

	/**
	 * @Description: 对用户进行删除
	 * @Param: [id]
	 * @return: com.woniuxy.util.ResponseData<?>
	 * @Author: Quan
	 * @Date: 2025/3/31
	 * @todo:当用户的车和卡都不需要绑定时，进行删除
	 */
	@Override
	public ResponseData<?> delete(Long id) {
		// 但是当用户有卡片时，不能删除，需要将充电卡禁用或者删除时，才可以对该用户进行删除操作
		// 判断用户是否还有电话卡
		List<Card> cards = cardMapper.queryCardByClientId(id);
		if (!cards.isEmpty()) {
			return ResponseData.fail(ResponseEnum.DO_NOT_DELETE, cards.stream().map(Card::getId).collect(Collectors.toList()));
		}
		// 删除用户，同时将他的车一并删除
		clientMapper.deleteClientById(id);
		// 删除用户持有的车辆信息
		vehicleMapper.delVehicleByClientId(id);
		return ResponseData.ok();
	}

	/**
	 * @Description: 查询客户的类型
	 * @Param: []
	 * @return: com.woniuxy.util.ResponseData<?>
	 * @Author: Quan
	 * @Date: 2025/4/2
	 */
	@Override
	public ResponseData<?> queryClientType() {
		return ResponseData.ok(RedisAboutDicUtils.saveAndReturnDicToRedis(redisTemplate, REDIS_KEY_CONST_CLIENTTYPE, clientMapper::queryClientType));
	}

	/**
	 * @Description: 通过用户id查询详情与名下的车辆
	 * @Param: [id]
	 * @return: com.woniuxy.util.ResponseData<?>
	 * @Author: Quan
	 * @Date: 2025/4/2
	 */
	@Override
	public ResponseData<?> queryClientBindVehicleByClientId(Long id) {
		ClientDetailDTO clientDetailDTOS = clientMapper.queryClientBindVehicleByClientId(id);
		return ResponseData.ok(clientDetailDTOS);
	}

	@Override
	public ResponseData<?> uploadImg(MultipartFile file) throws Exception {
		String imgSrc = minioUtils.uploadFile(file);
		return ResponseData.ok(imgSrc);
	}

	/**
	 * @Description: 解绑对应id的车辆, 用户持车数-1
	 * @Param: [id]
	 * @return: com.woniuxy.util.ResponseData<?>
	 * @Author: Quan
	 * @Date: 2025/4/2
	 */
	@Override
	public ResponseData<?> unbindVehicle(UnbindVehicleDTO unbindVehicleDTO) {
		// 解绑对应id的车辆
		clientMapper.unbindVehicle(unbindVehicleDTO.getVehicleId());
		// 查询对应用户id的持有的车辆
		List<Vehicle> vehicles = vehicleMapper.queryVehicleByClientId(unbindVehicleDTO.getClientId());
		List<VehicleDisplayForClientDetailDTO> vehicleDisplayForClientDetailDTOS = ListValueConvertUtils.listConvert(vehicles, VehicleDisplayForClientDetailDTO::new);
		unbindVehicleDTO.setVehicleList(vehicleDisplayForClientDetailDTOS);

		// 使对应的用户数-1,并或者持有车的数量
		clientMapper.updateHoldCarNumById(unbindVehicleDTO.getClientId(), -1);
		unbindVehicleDTO.setHoldCarNum(vehicles.size());
		return ResponseData.ok(unbindVehicleDTO);
	}

	/**
	 * @Description: 查询没有绑定的的车辆，共前端展示选择
	 * @Param: [vehicle]
	 * @return: com.woniuxy.util.ResponseData<?>
	 * @Author: Quan
	 * @Date: 2025/4/2
	 */
	@Override
	public ResponseData<?> queryUnbindVehicle(PageParam<VehicleDisplayForClientDetailDTO> pageParam) {
		PageInfo<VehicleDisplayForClientDetailDTO> pageInfo = pageHelperUtil.getPageInfo(pageParam, clientMapper::queryUnbindVehicle, VehicleDisplayForClientDetailDTO::new);
		return ResponseData.ok(pageInfo);
	}

	@Override
	public ResponseData<?> bindVehicle(UnbindVehicleDTO unbindVehicleDTO) {
		unbindVehicleDTO.setClientName(clientMapper.queryClientById(unbindVehicleDTO.getClientId()).getClientName());
		// 解绑对应id的车辆
		clientMapper.bindVehicle(unbindVehicleDTO);
		// 查询对应用户id的持有的车辆
		List<Vehicle> vehicles = vehicleMapper.queryVehicleByClientId(unbindVehicleDTO.getClientId());
		List<VehicleDisplayForClientDetailDTO> vehicleDisplayForClientDetailDTOS = ListValueConvertUtils.listConvert(vehicles, VehicleDisplayForClientDetailDTO::new);
		unbindVehicleDTO.setVehicleList(vehicleDisplayForClientDetailDTOS);

		// 使对应的用户数-1,并或者持有车的数量
		clientMapper.updateHoldCarNumById(unbindVehicleDTO.getClientId(), 1);
		unbindVehicleDTO.setHoldCarNum(vehicles.size());
		return ResponseData.ok(unbindVehicleDTO);
	}

	/**
	 * @Description: 更新客户的数据
	 * @Param: [clientDetailDTO]
	 * @return: com.woniuxy.util.ResponseData<?>
	 * @Author: Quan
	 * @Date: 2025/4/2
	 */
	@Override
	public ResponseData<?> update(ClientDetailDTO clientDetailDTO) {
		// 同步value到对应的字段
		// 查询clientType
		// 先判断redis中是否有该数据
		HashOperations<String, Object, Object> hash = redisTemplate.opsForHash();
		String clientType = (String) hash.get(REDIS_KEY_CONST_CLIENTTYPE, clientDetailDTO.getClientTypeId() + "");
		if (clientType == null) {
			RedisAboutDicUtils.saveAndReturnDicToRedis(redisTemplate, REDIS_KEY_CONST_CLIENTTYPE, clientMapper::queryClientType);
			clientType = (String) hash.get(REDIS_KEY_CONST_CLIENTTYPE, clientDetailDTO.getClientTypeId());
		}
		clientDetailDTO.setClientTypeValue(clientType);

		// 查询clientType
		// 先判断redis中是否有该数据
		String accountType = (String) hash.get(REDIS_KEY_CONST_ACCOUNTTYPE, clientDetailDTO.getAccountTypeId() + "");
		if (clientType == null) {
			RedisAboutDicUtils.saveAndReturnDicToRedis(redisTemplate, REDIS_KEY_CONST_ACCOUNTTYPE, clientMapper::queryAccountType);
			accountType = (String) hash.get(REDIS_KEY_CONST_ACCOUNTTYPE, clientDetailDTO.getClientTypeId());
		}
		clientDetailDTO.setAccountTypeValue(accountType);

		clientMapper.updateClient(clientDetailDTO);
		return ResponseData.ok();
	}

	/**
	 * @Description: 从字典表中查询支付类型并交给前端
	 * @Param: []
	 * @return: com.woniuxy.util.ResponseData<?>
	 * @Author: Quan
	 * @Date: 2025/4/3
	 */
	@Override
	public ResponseData<?> queryAccountType() {
		return ResponseData.ok(RedisAboutDicUtils.saveAndReturnDicToRedis(redisTemplate, REDIS_KEY_CONST_ACCOUNTTYPE, clientMapper::queryAccountType));
	}

	/**
	 * @Description: 添加客户信息,
	 * @Param: [clientDetailDTO]
	 * @return: com.woniuxy.util.ResponseData<?>
	 * @Author: Quan
	 * @Date: 2025/4/3
	 */
	@Override
	public ResponseData<?> addClient(ClientDetailDTO clientDetailDTO) {
		// 同步value到对应的字段
		// 查询clientType
		// 先判断redis中是否有该数据
		HashOperations<String, Object, Object> hash = redisTemplate.opsForHash();
		String clientType = (String) hash.get(REDIS_KEY_CONST_CLIENTTYPE, clientDetailDTO.getClientTypeId() + "");
		if (clientType == null) {
			RedisAboutDicUtils.saveAndReturnDicToRedis(redisTemplate, REDIS_KEY_CONST_CLIENTTYPE, clientMapper::queryClientType);
			clientType = (String) hash.get(REDIS_KEY_CONST_CLIENTTYPE, clientDetailDTO.getClientTypeId());
		}
		clientDetailDTO.setClientTypeValue(clientType);

		// 查询clientType
		// 先判断redis中是否有该数据
		String accountType = (String) hash.get(REDIS_KEY_CONST_ACCOUNTTYPE, clientDetailDTO.getAccountTypeId() + "");
		if (clientType == null) {
			RedisAboutDicUtils.saveAndReturnDicToRedis(redisTemplate, REDIS_KEY_CONST_ACCOUNTTYPE, clientMapper::queryAccountType);
			accountType = (String) hash.get(REDIS_KEY_CONST_ACCOUNTTYPE, clientDetailDTO.getClientTypeId());
		}
		clientDetailDTO.setAccountTypeValue(accountType);
		// 将密码进行加密
		String md5PWD = SecureUtil.md5(clientDetailDTO.getPassword() + "1a2b3c4d");
		clientDetailDTO.setPassword(md5PWD);

		// 添加用户信息到mybatis中吗
		clientMapper.addClient(clientDetailDTO);

		return ResponseData.ok(clientDetailDTO.getId());
	}

	/**
	 * @Description: 判断用户是否持有充电卡，批量对客户的信息进行删除
	 * @Param: [ids]
	 * @return: com.woniuxy.util.ResponseData<?>
	 * @Author: Quan
	 * @Date: 2025/4/7
	 */
	@Override
	public ResponseData<?> batchDelClient(List<Long> ids) {
		List<Card> cards = cardMapper.batchQueryCardByClientIds(ids);
		if (!cards.isEmpty()) {
			return ResponseData.fail(ResponseEnum.DO_NOT_DELETE, cards.stream().map(Card::getClientName).collect(Collectors.toSet()));
		}
		cardMapper.batchDelCardById(ids);
		vehicleMapper.batchDelVehicleByClientId(ids);
		return ResponseData.ok();
	}

	/**
	 * @Description: 刷新用户的持车数
	 * @Param: []
	 * @return: com.woniuxy.util.ResponseData<?>
	 * @Author: Quan
	 * @Date: 2025/4/7
	 */
	@Override
	public ResponseData<?> refresh() {
		return clientMapper.refresh();
	}

	/**
	 * @Description: 查询client的总数，得到总注册人数
	 * @Param: []
	 * @return: com.woniuxy.util.ResponseData<?>
	 * @Author: DirtyFlower
	 * @Date: 2025/4/7
	 */
	@Override
	public ResponseData<?> queryClientNumber() {
		return ResponseData.ok(clientMapper.queryClientNumber());
	}
	/**
	 * @Description: 查询client的总数，得到总注册人数
	 * @Param: []
	 * @return: com.woniuxy.util.ResponseData<?>
	 * @Author: DirtyFlower
	 * @Date: 2025/4/7
	 */
	@Override
	public ResponseData<?> queryClientNumberToday() {
		return ResponseData.ok(clientMapper.queryClientNumberToday());
	}
}
